/***********************************************/
/**
* @file gpsRapidIAU2000EarthOrientationParameter.cpp
*
* @brief Read Earth Orientation Parameter from GPS rapid file format. gpsrapid.daily/out
*
* @author Andreas KVas
* @date 2016-03-21
*
*/
/***********************************************/

// Latex documentation
#define DOCSTRING docstring
static const char* docstring = R"(
Read a IERS Earth orientation rapid data and prediction file (gpsrapid.xxx)
and write it as \configFile{outputfileEOP}{earthOrientationParameter}.
)";

/***********************************************/

#include "programs/program.h"
#include "inputOutput/file.h"
#include "files/fileEarthOrientationParameter.h"

/***** CLASS ***********************************/

/** @brief Read Earth Orientation Parameter.
* @ingroup programsConversionGroup */
class GPSRapid2EarthOrientationParameter
{
public:
    void run(Config& config, Parallel::CommunicatorPtr comm);
};

GROOPS_REGISTER_PROGRAM(GPSRapid2EarthOrientationParameter, SINGLEPROCESS, "read Earth Orientation Parameter", Conversion)

/***********************************************/

void GPSRapid2EarthOrientationParameter::run(Config& config, Parallel::CommunicatorPtr /*comm*/)
{
    try
    {
        FileName inName, outName;
        Time timeStart = Time();
        Time timeEnd = date2time(9999, 1, 1);

        readConfig(config, "outputfileEOP", outName, Config::MUSTSET, "", "");
        readConfig(config, "inputfile", inName, Config::MUSTSET, "", "");
        readConfig(config, "timeStart", timeStart, Config::OPTIONAL, "", "");
        readConfig(config, "timeEnd", timeEnd, Config::OPTIONAL, "", "");
        if (isCreateSchema(config)) return;

        // Erdrotationsparameter einlesen
        // ------------------------------
        logStatus << "read input file <" << inName << ">" << Log::endl;
        InFile file(inName);

        std::vector<Double> mjd, xp, yp, du;
        std::string line;
        while (std::getline(file, line))
        {
            if (line.empty())
                continue;

            Double _mjd, _xp, _yp, _du;
            if (!(std::stringstream(line.substr(1, 5)) >> _mjd))
                throw(Exception("Error reading MJD from EOP file."));

            Time time = mjd2time(_mjd);
            if ((time < timeStart) || (time > timeEnd))
                continue;

            if (!(std::stringstream(line.substr(7, 7)) >> _xp)) _xp = xp.back();
            if (!(std::stringstream(line.substr(22, 7)) >> _yp)) _yp = yp.back();
            if (!(std::stringstream(line.substr(37, 8)) >> _du)) _du = du.back();

            mjd.push_back(_mjd);
            xp.push_back(_xp);
            yp.push_back(_yp);
            du.push_back(_du);
        }

        logInfo << "  count = " << mjd.size() << Log::endl;
        logInfo << "  start = " << mjd2time(mjd.at(0)).dateTimeStr() << Log::endl;
        logInfo << "  end   = " << mjd2time(mjd.back()).dateTimeStr() << Log::endl;

        Matrix EOP(mjd.size(), 7);
        for (UInt i = 0; i < EOP.rows(); i++)
        {
            EOP(i, 0) = mjd.at(i);
            EOP(i, 1) = xp.at(i);
            EOP(i, 2) = yp.at(i);
            EOP(i, 3) = du.at(i);
            EOP(i, 4) = 0;
            EOP(i, 5) = 0;
            EOP(i, 6) = 0;
        }

        // Save to file
        // ------------
        logStatus << "write EOPs" << Log::endl;
        writeFileEarthOrientationParameter(outName, EOP);
    }
    catch (std::exception& e)
    {
        GROOPS_RETHROW(e)
    }
}

/***********************************************/
